package com.wan37.logic.guild.handler;

import com.wan37.logic.component.Worker;
import com.wan37.logic.db.AsynDBManager;
import com.wan37.logic.domain.vo.MessageVO;
import com.wan37.logic.global.reference.SpringContextHolder;
import com.wan37.logic.guild.cache.GuildCache;
import com.wan37.logic.listener.EventDispatcher;
import com.wan37.logic.listener.event.EventType;
import com.wan37.logic.listener.event.user.UserAddGuildEvent;
import com.wan37.protobuf.constant.GuildJobLabel;
import com.wan37.logic.guild.domain.vo.GuildUserVO;
import com.wan37.logic.guild.domain.vo.GuildVO;
import com.wan37.logic.guild.domain.vo.GuildWarehouseVO;
import com.wan37.logic.guild.service.GuildService;
import com.wan37.logic.guild.service.GuildUserService;
import com.wan37.logic.guild.service.GuildWarehouseService;
import com.wan37.logic.guild.util.GuildRouteUtil;
import com.wan37.logic.handler.MsgHandler;
import com.wan37.logic.service.UserWeaponryService;
import com.wan37.logic.service.cache.UserServiceCache;
import com.wan37.protobuf.constant.BackpackLabel;
import com.wan37.protobuf.constant.CommonGuild;
import com.wan37.protobuf.message.client2server.game.GameGuild;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;

/**
 * @author : luoyong
 * @date : 2020-08-03 16:17
 **/
public class CGameGuildHandler extends MsgHandler {
    private final Logger logger = LoggerFactory.getLogger(CGameGuildHandler.class);
    private GuildCache guildCache;
    private AsynDBManager asynDBManager;
    private GuildService guildService;
    private GuildUserService guildUserService;
    private GuildWarehouseService guildWarehouseService;
    private GuildRouteUtil guildRouteUtil;
    private UserServiceCache userServiceCache;
    private UserWeaponryService userWeaponryService;
    /**
     * MsgHandler构造函数
     *
     * @param messageVO
     */
    public CGameGuildHandler(MessageVO messageVO) {
        super(messageVO);
        this.guildCache = SpringContextHolder.getBean("guildCache");
        this.guildRouteUtil = SpringContextHolder.getBean("guildRouteUtil");
        this.userServiceCache = SpringContextHolder.getBean("userServiceCache");
        this.asynDBManager = SpringContextHolder.getBean("asynDBManager");
        this.guildService = SpringContextHolder.getBean("guildService");
        this.guildUserService = SpringContextHolder.getBean("guildUserService");
        this.guildWarehouseService = SpringContextHolder.getBean("guildWarehouseService");
        this.userWeaponryService = SpringContextHolder.getBean("userWeaponryService");
    }

    @Override
    public void execute(Worker worker) throws Exception {
        GameGuild.GuildMsg guildMsg = (GameGuild.GuildMsg) messageVO.getMessage();
        int code = guildMsg.getCode();
        String userId = messageVO.getUserId();
        switch (code){
            case CommonGuild.GET_ALL:
                getAll(userId);
                break;
            case CommonGuild.ADD_GUILD:
                GuildVO guildVO1 = new GuildVO(guildMsg.getGuild());
                if (userServiceCache.getUserServiceMap().get(userId).getGuildId() != null){
                    guildRouteUtil.sendGuildResponse(CommonGuild.ERROR, userId, "你已经在一个公会中，不允许创建公会！！");
                    break;
                }
                for (GuildCache.GuildIn guildIn1 : guildCache.getGuildInMap().values()){
                    if (guildIn1.getGuildVO().getName().equals(guildVO1.getName())){
                        guildRouteUtil.sendGuildResponse(CommonGuild.ERROR, userId, "公会名已被使用！！");
                        return;
                    }
                }
                //添加公会id到用户缓存中
                userServiceCache.getUserServiceMap().get(userId).setGuildId(guildVO1.getGuildId());
                //添加公会信息
                GuildCache.GuildIn guildIn = guildCache.new GuildIn();
                guildIn.setGuildVO(guildVO1);
                //添加公会成员信息
                GuildUserVO guildUserVO5 = new GuildUserVO(guildVO1.getGuildId(), guildVO1.getHeaderId(), GuildJobLabel.HEADER.value);
                guildIn.getGuildUserVOList().add(guildUserVO5);
                guildCache.getGuildInMap().put(guildVO1.getGuildId(), guildIn);
                asynDBManager.distributeWork(userId, ()->guildService.save(guildVO1));
                asynDBManager.distributeWork(userId, ()->guildUserService.save(guildUserVO5));
                guildRouteUtil.sendGuildResponse(CommonGuild.ADD_GUILD, userId, guildVO1, guildCache.getGuildInMap().get(guildVO1.getGuildId()).getGuildUserVOList(), null);
                EventDispatcher.getInstance().fireEvent(new UserAddGuildEvent(EventType.ADD_GUILD, userId));
                break;
            case CommonGuild.UPDATE_GUILD:
                GuildVO guildVO2 = new GuildVO(guildMsg.getGuild());
                guildCache.getGuildInMap().get(guildVO2.getGuildId()).setGuildVO(guildVO2);
                asynDBManager.distributeWork(userId, ()->guildService.update(guildVO2));
                guildRouteUtil.sendGuildResponse(code, userId, guildVO2,null,null);
                break;
            case CommonGuild.DELETE_GUILD:
                GuildVO guildVO3 = new GuildVO(guildMsg.getGuild());
                userServiceCache.getUserServiceMap().get(userId).setGuildId(null);
                if (guildCache.getGuildInMap().get(guildVO3.getGuildId()).getGuildVO().getHeaderId().equals(userId)){
                    for (GuildUserVO guildUserVO : guildCache.getGuildInMap().get(guildVO3.getGuildId()).getGuildUserVOList()){
                        guildRouteUtil.sendGuildResponse(CommonGuild.HEADER_DELETE_GUILD, guildUserVO.getUserId(), "会长解散了公会！", guildVO3);
                    }
                    for (GuildUserVO guildUserVO : guildCache.getGuildInMap().get(guildVO3.getGuildId()).getGuildUserVOList()){
                        if (userServiceCache.getUserServiceMap().containsKey(guildUserVO.getUserId())){
                            userServiceCache.getUserServiceMap().get(guildUserVO.getUserId()).setGuildId(null);
                        }
                    }
                    guildCache.getGuildInMap().remove(guildVO3.getGuildId());
                    asynDBManager.distributeWork(userId, ()->guildService.deleteByGuildId(guildVO3.getGuildId()));
                }else {
                    for (GuildUserVO guildUserVO : guildCache.getGuildInMap().get(guildVO3.getGuildId()).getGuildUserVOList()){
                        if (guildUserVO.getUserId().equals(userId)){
                            guildCache.getGuildInMap().get(guildVO3.getGuildId()).getGuildUserVOList().remove(guildUserVO);
                            asynDBManager.distributeWork(userId,()->guildUserService
                                    .deleteByGuildIdAndUserId(guildUserVO.getGuildId(), guildUserVO.getUserId()));
                            guildRouteUtil.sendGuildResponse(CommonGuild.SELF_DELETE_GUILD, userId, "退出公会成功！", guildVO3);
                            break;
                        }
                    }
                    for (GuildUserVO guildUserVO : guildCache.getGuildInMap().get(guildVO3.getGuildId()).getGuildUserVOList()){
                        if(guildUserVO.getJob() == GuildJobLabel.HEADER.value || guildUserVO.getJob() == GuildJobLabel.VICE_HEADER.value){
                            guildRouteUtil.sendGuildResponse(CommonGuild.OTHER_DELETE_GUILD, guildUserVO.getUserId(), userId + " 退出了公会！",
                                    guildCache.getGuildInMap().get(guildVO3.getGuildId()).getGuildUserVOList());
                        }
                    }
                }
                break;
            case CommonGuild.APPLY_GUILD_USER:
                GuildVO guildVO4 = new GuildVO(guildMsg.getGuild());
                if (guildCache.getGuildInMap().containsKey(guildVO4.getGuildId())){
                    guildVO4 = guildCache.getGuildInMap().get(guildVO4.getGuildId()).getGuildVO();
                    guildCache.getGuildInMap().get(guildVO4.getGuildId()).getApplyUserIdList().add(guildMsg.getString());
                    guildRouteUtil.sendGuildResponse(code, userId, "申请成功！");
                    for (GuildUserVO guildUserVO : guildCache.getGuildInMap().get(guildVO4.getGuildId()).getGuildUserVOList()){
                        if (guildUserVO.getJob() == GuildJobLabel.HEADER.value
                                || guildUserVO.getJob() == GuildJobLabel.VICE_HEADER.value){
                            guildRouteUtil.sendGuildResponse(code, guildUserVO.getUserId(), "有用户申请加入公会！");

                        }
                    }
                    guildRouteUtil.sendGuildResponse(CommonGuild.GET_APPLY_USER_ID, guildVO4.getHeaderId(),
                            guildCache.getGuildInMap().get(guildVO4.getGuildId()).getApplyUserIdList());
                }
                break;
            case CommonGuild.APPLY_GUILD_USER_DISAGREE:
                GuildVO guildVO9 = new GuildVO(guildMsg.getGuild());
                guildCache.getGuildInMap().get(guildVO9.getGuildId()).getApplyUserIdList().remove(guildMsg.getString());
                guildRouteUtil.sendGuildResponse(code, userId,
                        guildCache.getGuildInMap().get(guildVO9.getGuildId()).getApplyUserIdList());
                break;
            case CommonGuild.GET_APPLY_USER_ID:
                GuildVO guildVO5 = new GuildVO(guildMsg.getGuild());
                guildRouteUtil.sendGuildResponse(code, userId,
                        guildCache.getGuildInMap().get(guildVO5.getGuildId()).getApplyUserIdList());
                break;
            case CommonGuild.ADD_GUILD_USER:
                GuildVO guildVO6 = new GuildVO(guildMsg.getGuild());
                GuildCache.GuildIn guildIn1 = guildCache.getGuildInMap().get(guildVO6.getGuildId());
                for (GuildUserVO guildUserVO : guildIn1.getGuildUserVOList()){
                    if (guildUserVO.getUserId().equals(userId)){
                        if (guildUserVO.getJob() == GuildJobLabel.HEADER.value
                                || guildUserVO.getJob() == GuildJobLabel.VICE_HEADER.value){
                            guildIn1.getApplyUserIdList().remove(guildMsg.getString());
                            GuildUserVO guildUserVO1 = new GuildUserVO(guildVO6.getGuildId(), guildMsg.getString(), GuildJobLabel.USER.value);
                            guildIn1.getGuildUserVOList().add(guildUserVO1);
                            asynDBManager.distributeWork(userId, ()->guildUserService.save(guildUserVO1));
                            EventDispatcher.getInstance().fireEvent(new UserAddGuildEvent(EventType.ADD_GUILD, guildMsg.getString()));
                            guildRouteUtil.sendGuildResponse(code, userId, null, guildIn1.getGuildUserVOList(), null);
                            userServiceCache.getUserServiceMap().get(guildMsg.getString()).setGuildId(guildVO6.getGuildId());
                            getAll(guildMsg.getString());
                        }else {
                            guildRouteUtil.sendGuildResponse(CommonGuild.ERROR, userId, "你没有权限！");
                        }
                        break;
                    }
                }
                break;
            case CommonGuild.UPDATE_GUILD_USER_JOB:
                GameGuild.GuildUser guildUser = guildMsg.getGuildUser(0);
                GuildUserVO guildUserVO = new GuildUserVO(guildUser);
                for (GuildUserVO guildUserVO1 : guildCache.getGuildInMap().get(guildUserVO.getGuildId()).getGuildUserVOList()){
                    if (guildUserVO1.getUserId().equals(userId)){
                        if (guildUserVO1.getJob() != GuildJobLabel.HEADER.value){
                            guildRouteUtil.sendGuildResponse(CommonGuild.ERROR, userId, "你不是会长，没有权限修改会员职位！");
                        }else {
                            //如果会员的职位修改为会长，则为转让公会，需要修改公会信息，以及修改原会长信息。
                            if (guildUserVO.getJob() == GuildJobLabel.HEADER.value){
                                guildCache.getGuildInMap().get(guildUserVO1.getGuildId()).getGuildVO().setHeaderId(guildUserVO.getUserId());
                                asynDBManager.distributeWork(userId,()->guildService.update
                                        (guildCache.getGuildInMap().get(guildUserVO1.getGuildId()).getGuildVO()));
                                guildUserVO1.setJob(GuildJobLabel.USER.value);
                                asynDBManager.distributeWork(userId, ()->guildUserService.update(guildUserVO1));
                            }
                        }
                    }
                }
                for (GuildUserVO guildUserVO1 : guildCache.getGuildInMap().get(guildUser.getGuildId()).getGuildUserVOList()){
                    if (guildUserVO1.getUserId().equals(guildUserVO.getUserId())){
                        guildUserVO1.setJob(guildUserVO.getJob());
                    }
                }
                asynDBManager.distributeWork(userId, ()->guildUserService.update(guildUserVO));
                guildRouteUtil.sendGuildResponse(CommonGuild.UPDATE_GUILD_USER_JOB, userId, null, guildCache.getGuildInMap().get(guildUser.getGuildId()).getGuildUserVOList(), null);
                break;
            case CommonGuild.DELETE_GUILD_USER:
                GuildVO guildVO7 = new GuildVO(guildMsg.getGuild());
                if (userId.equals(guildMsg.getString())){
                    guildRouteUtil.sendGuildResponse(CommonGuild.ERROR, userId, "不允许踢自己出公会！！！");
                    break;
                }
                if (guildVO7.getHeaderId().equals(guildMsg.getString())){
                    guildRouteUtil.sendGuildResponse(CommonGuild.ERROR, userId, "不允许踢会长出公会！！！");
                    break;
                }
                for (GuildUserVO guildUserVO1 : guildCache.getGuildInMap().get(guildVO7.getGuildId()).getGuildUserVOList()){
                    if (guildUserVO1.getUserId().equals(userId)){
                        if (guildUserVO1.getJob() == GuildJobLabel.HEADER.value || guildUserVO1.getJob() == GuildJobLabel.VICE_HEADER.value){
                            for (GuildUserVO guildUserVO2 : guildCache.getGuildInMap().get(guildVO7.getGuildId()).getGuildUserVOList()){
                                if (guildUserVO2.getUserId().equals(guildMsg.getString())){
                                    userServiceCache.getUserServiceMap().get(guildUserVO2.getUserId()).setGuildId(null);
                                    guildCache.getGuildInMap().get(guildVO7.getGuildId()).getGuildUserVOList().remove(guildUserVO2);
                                    asynDBManager.distributeWork(userId,()->guildUserService
                                            .deleteByGuildIdAndUserId(guildUserVO2.getGuildId(), guildUserVO2.getUserId()));
                                    guildRouteUtil.sendGuildResponse(CommonGuild.DELETE_GUILD_USER, guildMsg.getString(), "你被踢出了公会！", guildVO7);
                                    break;
                                }
                            }
                            for (GuildUserVO guildUserVO2 : guildCache.getGuildInMap().get(guildVO7.getGuildId()).getGuildUserVOList()){
                                if(guildUserVO2.getJob() == GuildJobLabel.HEADER.value || guildUserVO2.getJob() == GuildJobLabel.VICE_HEADER.value){
                                    guildRouteUtil.sendGuildResponse(CommonGuild.DELETE_GUILD_USER, guildUserVO2.getUserId(), guildMsg.getString() + " 被"+ userId +"踢出了公会！");
                                }
                            }
                        }
                        break;
                    }
                }
                break;
                case CommonGuild.ADD_GUILD_WAREHOUSE:
                    GuildVO guildVO8 = new GuildVO(guildMsg.getGuild());
                    if (!userServiceCache.getUserServiceMap().get(userId)
                            .getWeaponryVOMap().containsKey(guildMsg.getString())){
                        guildRouteUtil.sendGuildResponse(CommonGuild.ERROR, userId, "装备不存在！");
                    }
                    if (!userServiceCache.getUserServiceMap().get(userId)
                            .getWeaponryVOMap().get(guildMsg.getString()).getUsage().equals(BackpackLabel.WEAPONRY_UNUSED)){
                        guildRouteUtil.sendGuildResponse(CommonGuild.ERROR, userId, "装备已经使用的不允许捐赠！");
                    }
                    GuildWarehouseVO guildWarehouseVO = new GuildWarehouseVO();
                    guildWarehouseVO.setGuildId(guildVO8.getGuildId());
                    guildWarehouseVO.setBackpackId(userServiceCache.getUserServiceMap()
                            .get(userId).getWeaponryVOMap().get(guildMsg.getString()).getBackpackId());
                    guildCache.getGuildInMap().get(guildVO8.getGuildId()).getGuildWarehouseVOList().add(guildWarehouseVO);
                    userServiceCache.getUserServiceMap().get(userId).getWeaponryVOMap().remove(guildMsg.getString());
                    asynDBManager.distributeWork(userId, ()->userWeaponryService.deleteBySelfWeaponryId(guildMsg.getString()));
                    for (GuildUserVO guildUserVO1 : guildCache.getGuildInMap().get(guildVO8.getGuildId()).getGuildUserVOList()){
                        guildRouteUtil.sendGuildResponse(code, guildUserVO1.getUserId(), null,
                                null, guildCache.getGuildInMap().get(guildVO8.getGuildId()).getGuildWarehouseVOList());
                    }
                    break;
            default:
                break;
        }
    }
    public void getAll(String userId){
        GuildVO guildVO = null;
        List<GuildUserVO> guildUserVOList = null;
        List<GuildWarehouseVO> guildWarehouseVOList = null;
        if (userServiceCache.getUserServiceMap().get(userId).getGuildId() != null){
            GuildCache.GuildIn guildIn = guildCache.getGuildInMap()
                    .get(userServiceCache.getUserServiceMap().get(userId).getGuildId());
            guildVO = guildIn.getGuildVO();
            guildUserVOList = guildIn.getGuildUserVOList();
            guildWarehouseVOList = guildIn.getGuildWarehouseVOList();
        }
        List<GameGuild.SimpleAllGuild> simpleAllGuildList = new ArrayList<>();
        for (GuildCache.GuildIn guildIn : guildCache.getGuildInMap().values()){
            GameGuild.SimpleAllGuild.Builder sagb = GameGuild.SimpleAllGuild.newBuilder();
            GuildVO guildVO1 = guildIn.getGuildVO();
            sagb.setName(guildVO1.getName());
            sagb.setLevel(guildVO1.getLevel());
            sagb.setGuildId(guildVO1.getGuildId());
            sagb.setCount(guildIn.getGuildUserVOList().size());
            simpleAllGuildList.add(sagb.build());
        }
        guildRouteUtil.sendGuildResponse(CommonGuild.GET_ALL,
                userId, guildVO, guildUserVOList, guildWarehouseVOList, simpleAllGuildList);
    }
}
